/** * Java Diagram Package; An extremely flexible and fast multipurpose diagram component for Swing. Copyright (C) 2001 Eric Crahen <crahen@cse.buffalo.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package diagram; import java.awt.Color; import java.awt.Component; import java.awt.FontMetrics; import java.awt.Insets; import java.awt.Point; import java.awt.geom.Rectangle2D; import javax.swing.JTextField; import javax.swing.UIManager; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.PlainDocument; import diagram.figures.PolyLink; /** * @class DefaultLabelRenderer * * @date 08-20-2001 * @author Eric Crahen * @version 1.0 * * This render paints a PolyLink as its label in the correct position */ public class DefaultLabelRenderer extends JTextField implements FigureRenderer { protected Insets insets = new Insets(0,0,0,0); protected Point p1 = new Point(); protected Point p2 = new Point(); private int lastWidth; private final static int MAXIMUM_WIDTH = 150; static { UIManager.put("label.foreground", Color.black); UIManager.put("label.background", Color.white); } public DefaultLabelRenderer() { setBackground(UIManager.getColor("label.background")); setForeground(UIManager.getColor("label.foreground")); } public Document createDefaultModel() { return new SimpleDocument(); } /** * */ public Component getRendererComponent(Diagram diagram, Figure figure, boolean isSelected) { Object label = diagram.getModel().getValue(figure); setText(label != null ? label.toString() : ""); return this; } /** * */ public Rectangle2D getDecoratedBounds(Diagram diagram, Figure figure, Rectangle2D rcBounds) { if(rcBounds == null) rcBounds = new Rectangle2D.Double(); return calculateLabelBounds((PolyLink)figure, getText(), rcBounds); } /** * Find the longest segment. Update the p1 & p2 members to contain the * segment to draw the label in. * * @param PolyLink */ protected void calculateSegment(PolyLink link) { double d, max = 0; int n = 0; // Find the longest segment p2 = (Point)link.getPN(1, p2); p1 = (Point)link.getSource().getConnection(p2, p1); max = p1.distance(p2); for(int i = 1; i < link.getSegmentCount() - 1; i++) { p1 = (Point)link.getPN(i, p1); p2 = (Point)link.getPN(i+1, p2); if((d = p1.distance(p2)) > max) { max = d; n = i; } } p2 = (Point)link.getPN(link.getPointCount() - 2, p2); p1 = (Point)link.getSink().getConnection(p2, p1); if((d = p1.distance(p2)) > max) n = link.getSegmentCount() - 1; // Get the longest point p2 = (Point)link.getPN(n, p2); p1 = (Point)link.getPN(n+1, p1); } /** * Calculate where the label should be placed * * @param PolyLink * @param Rectangle2D rectangle to fill with the bounds */ protected Rectangle2D calculateLabelBounds(PolyLink link, String text, Rectangle2D rc) { calculateSegment(link); double x1 = p1.x; double y1 = p1.y; double x2 = p2.x; double y2 = p2.y; double dx = (x1 > x2) ? (x1 - x2)*-1 : (x2 - x1); double dy = (y1 > y2) ? (y1 - y2)*-1 : (y2 - y1); FontMetrics metrics = getFontMetrics( getFont() ); insets = getInsets(insets); int w = metrics.charsWidth(text.toCharArray(), 0, text.length()); w += insets.left + insets.right; w = Math.min(MAXIMUM_WIDTH, w); int h = metrics.getHeight(); h += insets.top + insets.bottom; dx -= w; dy -= h; dx /= 2; dy /= 2; y1 -= insets.top; x1 -= insets.left; lastWidth = w; if(rc == null) return new Rectangle2D.Double((x1 + dx), (y1 + dy), w, h); rc.setFrame((x1 + dx), (y1 + dy), w, h); return rc; } /** * Change the width to fit the text */ protected void updateBounds() { String text = getText(); FontMetrics metrics = getFontMetrics( getFont() ); int w = metrics.charsWidth(text.toCharArray(), 0, text.length()); w = Math.min(MAXIMUM_WIDTH, w); int dx = (w - lastWidth); lastWidth = w; setBounds(getX()-dx/2, getY(), Math.max(getWidth()+dx, 5), getHeight()); } /** * Modified document that notifies the component of the text changing. */ class SimpleDocument extends PlainDocument { public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { super.insertString(offs, str, a); updateBounds(); } public void remove(int offs, int len) throws BadLocationException { super.remove(offs, len); updateBounds(); } } }